#ifndef THREADPOOL_H
#define THREADPOOL_H

#include <thread>
#include <queue>
#include <functional>
#include "../lock/locker.h"


class ThreadPool{
public:
    explicit ThreadPool(uint32_t worker_num = 8){
        for (int i = 0; i < worker_num; ++i) {
            std::thread([this] {
                this->m_lock.lock();
                while (true){
                    if (this->m_is_close) {
                        break;
                    }
                    if (!this->m_task_queue.empty()){
                        auto exec_task = std::move(this->m_task_queue.front());
                        this->m_task_queue.pop();
                        this->m_lock.unlock();
                        exec_task();
                        this->m_lock.lock();
                    } else {
                        this->m_cond.wait(this->m_lock.get());
                    }
                }
                this->m_lock.unlock();
            }).detach();
        }
    }

    ~ThreadPool(){
        m_lock.lock();
        m_is_close = true;
        m_lock.unlock();
        m_cond.broadcast();
    };

    template<class F> void add_task(F&& task){
        m_lock.lock();
        m_task_queue.emplace(std::forward<F>(task));
        m_lock.unlock();
        m_cond.signal();
    }


private:
    bool m_is_close = false;
    std::queue<std::function<void()>> m_task_queue;
    Locker m_lock;
    Condition m_cond;
};


#endif //THREADPOOL_H
